/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.model.femModel.element;

import java.util.ArrayList;

import br.ufmg.dees.insane.materialMedia.degeneration.Degeneration;
import br.ufmg.dees.insane.materialMedia.degeneration.PrescribedDegeneration;
import br.ufmg.dees.insane.model.femModel.elementNode.ElementNode;
import br.ufmg.dees.insane.model.femModel.node.Node;
import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IPoint3d;
import br.ufmg.dees.insane.util.IVector;

/**
 * A class representing a frame element.<p>
 * @author  Flavio, Roque, Samir
 * @version  1.0
 * @since  20/09/2006
 */

public class FrameElement extends Element {
	
	private static final long serialVersionUID = 1L;

	/** The possible keys for the Map. */
	public static final String DELTA_TEMP = "DELTA_TEMP";
	public static final String ELM_POINT_FORCES = "ELM_POINT_FORCES";
	public static final String ELM_LINE_FORCES = "ELM_LINE_FORCES";
	
	/**Constructs a FrameElement.*/	
	public FrameElement(){
	}

	/** Updates all variables of this element based on the nodal variables state.
	*/
	public void update(){
		
	}
	
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.model.femModel.element.Element#getElmCoefficient()
     */
    public double getElmCoefficient(){
    	return 1;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.model.femModel.element.Element#addDegeneration(br.ufmg.dees.insane.materialMedia.degeneration.Degeneration)
     */
    public void addDegeneration(Degeneration dg){
        this.degenerations.add(dg);
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.model.femModel.element.Element#initDegeneration()
     */
	public void initDegenerations(){
		
	}
	
	/**
	 * Returns this FrameElement's length
	 * @return This FrameElement's length
	 */
	public double getLength(){
		IPoint3d point1 = ((Node)this.getIncidence().get(0)).getPoint();
		IPoint3d point2 = ((Node)this.getIncidence().get(1)).getPoint();
		double length = point1.distance(point2);
		return length;
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Ix
	 * @return This FrameElement's PrescribedDegeneration's Ix
	 */
	public double getIx(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getIx());
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Iy
	 * @return This FrameElement's PrescribedDegeneration's Iy
	 */
	public double getIy(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getIy());
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Iz
	 * @return This FrameElement's PrescribedDegeneration's Iz
	 */
	public double getIz(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getIz());
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Area
	 * @return This FrameElement's PrescribedDegeneration's Area
	 */
	public double getArea(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getArea());
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Height
	 * @return This FrameElement's PrescribedDegeneration's Height
	 */
	public double getHeight(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getHeight());
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Form Factor for Y direction
	 * @return This FrameElement's PrescribedDegeneration's Form Factor for Y direction
	 */
	public double getFormFactorY(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getFormFactorY());
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Form Factor for Z direction
	 * @return This FrameElement's PrescribedDegeneration's Form Factor for Z direction
	 */
	public double getFormFactorZ(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getFormFactorZ());
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Material's Elasticity
	 * @return This FrameElement's PrescribedDegeneration's Material's Elasticity
	 */
	public double getElasticity(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getMaterial().getMaterialValues("ELASTICITY"));
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Material's Shear Modulus
	 * @return This FrameElement's PrescribedDegeneration's Material's Shear Modulus
	 */
	public double getShearModulus(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getMaterial().getMaterialValues("SHEAR_MODULUS"));
	}
	
	/**
	 * Returns this FrameElement's PrescribedDegeneration's Material's Thermal Coefficient
	 * @return This FrameElement's PrescribedDegeneration's Material's Thermal Coefficient
	 */
	public double getThermalCoefficient(){
		return (((PrescribedDegeneration)this.getDegenerations().get(0)).getMaterial().getMaterialValues("THERMAL_COEFF"));
	}
	
	/**
	 * Returns this FrameElement's liberations
	 * @return This FrameElement's liberations
	 */
	public boolean[] getLiberations(){
		int ndf = this.getNumberOfDegreesOfFreedom();
		boolean[] lib = new boolean[ndf];
		
		ElementNode en = (ElementNode)incidence.get(0);
		if (en.elementNodeValuesContainsKey(ElementNode.LIBERATIONS)) {
			for(int i=0; i<ndf/2; i++){
				lib[i]= en.getElementNodeValues(ElementNode.LIBERATIONS).getBooleanPointValue(i);
			}
		}
		en = (ElementNode)incidence.get(1);
		if (en.elementNodeValuesContainsKey(ElementNode.LIBERATIONS)) {
			for(int i=ndf/2; i<ndf; i++){
				lib[i]= en.getElementNodeValues(ElementNode.LIBERATIONS).getBooleanPointValue(i);
			}
		}
		return lib;
	}
	
	/**
	 * Returns this FrameElement's liberations
	 * @return This FrameElement's liberations
	 */
	public double[] getInitialEquivalentNodalForce(){
		int ndf = this.getNumberOfDegreesOfFreedom();
		double[] eqForce = new double[ndf];
		
		ElementNode en = (ElementNode)incidence.get(0);
		if (en.elementNodeValuesContainsKey(ElementNode.INITIAL_EQ_NODAL_FORCE)) {
			for(int i=0; i<ndf/2; i++){
				eqForce[i]= en.getElementNodeValues(ElementNode.INITIAL_EQ_NODAL_FORCE).getDoublePointValue(i);
			}
		}
		en = (ElementNode)incidence.get(1);
		if (en.elementNodeValuesContainsKey(ElementNode.INITIAL_EQ_NODAL_FORCE)) {
			for(int i=ndf/2; i<ndf; i++){
				eqForce[i]= en.getElementNodeValues(ElementNode.INITIAL_EQ_NODAL_FORCE).getDoublePointValue(i);
			}
		}
		return eqForce;
	}
	
	/**
	 * Returns this FrameElement's liberations
	 * @return This FrameElement's liberations
	 */
	public IVector getElmPreDisplacement(){
		int ndf = this.getNumberOfDegreesOfFreedom();
		IVector preDisp = new IVector(ndf);
		
		ElementNode en = (ElementNode)incidence.get(0);
		if (en.elementNodeValuesContainsKey(ElementNode.INITIAL_EQ_NODAL_FORCE)) {
			for(int i=0; i<ndf/2; i++){
				preDisp.setElement(i, en.getElementNodeValues(ElementNode.INITIAL_EQ_NODAL_FORCE).getDoublePointValue(i));
			}
		}
		en = (ElementNode)incidence.get(1);
		if (en.elementNodeValuesContainsKey(ElementNode.INITIAL_EQ_NODAL_FORCE)) {
			for(int i=ndf/2; i<ndf; i++){
				preDisp.setElement(i, en.getElementNodeValues(ElementNode.INITIAL_EQ_NODAL_FORCE).getDoublePointValue(i));
			}
		}
		return preDisp;
	}
	
	/**
	 * Returns an array with this FrameElement's properties
	 * @return An array with this FrameElement's properties
	 */
	public double[] getPropertiesArray(){
		double[] prop = new double[11];
		prop[0] = this.getLength();
		prop[1] = this.getElasticity();
		prop[2] = this.getShearModulus();
		prop[3] = this.getThermalCoefficient();
		prop[4] = this.getIx();
		prop[5] = this.getIy();
		prop[6] = this.getIz();
		prop[7] = this.getArea();
		prop[8] = this.getHeight();
		prop[9] = this.getFormFactorY();
		prop[10] = this.getFormFactorZ();
		return prop;
	}
	
	/**
	 * Returns an IMatrix (column) with this FrameElement's properties
	 * @return An IMatrix (column) with this FrameElement's properties
	 */
	public IMatrix getPropertiesMatrix(){
		IMatrix prop = new IMatrix(11, 0);
		prop.setElement(0, 0, this.getLength());
		prop.setElement(1, 0, this.getElasticity());
		prop.setElement(2, 0, this.getShearModulus());
		prop.setElement(3, 0, this.getThermalCoefficient());
		prop.setElement(4, 0, this.getIx());
		prop.setElement(5, 0, this.getIy());
		prop.setElement(6, 0, this.getIz());
		prop.setElement(7, 0, this.getArea());
		prop.setElement(8, 0, this.getHeight());
		prop.setElement(9, 0, this.getLength());
		prop.setElement(10, 0, this.getFormFactorY());
		prop.setElement(11, 0, this.getFormFactorZ());

		return prop;
	}

	@Override
	public IVector extrapolatesToNodes(ArrayList a, ArrayList d) {
		// TODO Auto-generated method stub
		return null;
	}
	
}

